package com.leadiv.cards;

import java.util.Vector;

/**
 * Card class
 * @author pborrego
 * A card class represents a real life playing card.
 * A deck of cards are able to be sorted and so uses the Comparable interace.
 */
public class Card implements Comparable<Card> {
    private String suit;
    private String face;
    private Double value;

    /**
     * Card
     * All cards are created using a suit, face and value.
     * @author pborrego
     * @param suit - suit of the card
     * @param face - face of the card
     * @param value - value of the card
     */
    public Card(String suit, String face, double value) {
        this.suit = suit;
        this.face = face;
        this.value = new Double(value);
    }

    /**
     * Card -- cloning constuctor
     * @author pborrego
     * @param c - card to copy
     */
    public Card(Card c) {
        this.suit = c.getSuit();
        this.face = c.getFace();
        this.value = c.getValue();
    }

    /**
     * cardFactory
     * @author pborrego
     * @param suits - an array of suit values for the set of cards to be created.
     * @param faces - an array of face values for the set of cards to be created.
     * @param values - an array of values for the set of cards to be created.
     * @return - a Deck of cards
     */
    public static Deck<? extends Card> cardFactory(String[] suits, String[] faces, double[] values)
    {
        Vector<Card> cards = new Vector<Card>();
        int i = 0;
        int j = 0;
        int cnt = 0;

        for(; i < suits.length; i++)
        {
            for(; j < faces.length; j++)
            {
                cards.add(new Card(suits[i], faces[j], values[j]));
                cnt++;
            }
            j = 0;
        }

        return new Deck<Card>(cards);
    }

    /**
     * printCard
     * Prints out the value, suit and face of the card. Used for testing.
     */
    public void printCard()
    {
        System.out.println(face + " of " + suit + " has a value of " + value.toString());
    }

    /**
     * getFace
     * @return - the face value of a card
     */
    public String getFace() {
        return face;
    }

    /**
     * setFace
     * @param face - the face value of the card
     */
    public void setFace(String face) {
        this.face = face;
    }

    /**
     * getSuit
     * @return - the suit of the card.
     */
    public String getSuit() {
        return suit;
    }

    /**
     * setSuit
     * @param suit - suit value of the card.
     */
    public void setSuit(String suit) {
        this.suit = suit;
    }

    /**
     * getValue
     * @return - the value of the card.
     */
    public Double getValue() {
        return value;
    }

    /**
     * setValue
     * @param value - value of the card
     */
    public void setValue(Double value) {
        this.value = value;
    }

    /**
     * equals
     * Overrides the object's equal to compare cards.
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Card other = (Card) obj;
        if ((this.suit == null) ? (other.suit != null) : !this.suit.equals(other.suit)) {
            return false;
        }
        if ((this.face == null) ? (other.face != null) : !this.face.equals(other.face)) {
            return false;
        }
        if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
            return false;
        }
        return true;
    }

    /**
     * Overrides the object's hashCode method.
     * @return
     */
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 97 * hash + (this.suit != null ? this.suit.hashCode() : 0);
        hash = 97 * hash + (this.face != null ? this.face.hashCode() : 0);
        hash = 97 * hash + (this.value != null ? this.value.hashCode() : 0);
        return hash;
    }

    /**
     * Overrides object's clone method and returns a Card object instead.
     * @return
     */
    @Override
    public Card clone() {
        return new Card(this.suit, this.face, this.value);
    }

    /**
     * Allows the Card to be sorted using the Collections.sort function.
     * @param c - Card to compare to this card.
     * @return 0 for equal. -1 if the current card (this) has a greater value
     * or suit. 1 if the current card (this) has a lesser value or suit.
     */
    public int compareTo(Card c) {

        if(this.getSuit().equals(c.getSuit())) {
            if(this.getValue() > c.getValue()) return -1;
            if(this.getValue() < c.getValue()) return 1;
            return 0;
        }

        return this.getSuit().compareTo(c.getSuit());
    }
}
